<template>
  <div class="message">
    <el-popover placement="bottom" @show="onShow" @hide="onHide" :width="380" trigger="click">
      <template #reference>
        <el-badge :value="unReadCount" class="item">
          <i :class="'iconfont icon-xiaoxi'" class="toolBar-icon"></i>
        </el-badge>
      </template>
      <el-tabs v-model="activeName">
        <el-tab-pane :label="`未读(${unReadCount})`" name="unread">
          <ul class="message-list" v-if="unReadCount > 0">
            <li class="message-item" v-for="item in unReadMessageList" :key="item._id" @click="onReadMessage(item)">
              <img v-if="item.type == 'TODO'" src="@/assets/images/msg04.png" alt="" class="message-icon" />
              <img v-else-if="item.type == 'NOTIFY'" src="@/assets/images/msg01.png" alt="" class="message-icon" />
              <img v-else src="@/assets/images/msg02.png" alt="" class="message-icon" />
              <div class="message-content">
                <span class="message-title">{{ item.title }}</span>
                <span class="message-date">{{ useTime(item.create_at).nowTime.value }}</span>
              </div>
            </li>
          </ul>
          <div v-else class="message-empty">
            <img src="@/assets/images/notData.png" alt="notData" />
            <div>暂无待办</div>
          </div>
        </el-tab-pane>
        <el-tab-pane :label="`已读(${readCount})`" name="read">
          <ul class="message-list" v-if="readCount > 0" ref="el">
            <li class="message-item" v-for="item in readMessageList" :key="item._id" @click="onOpenMessage(item)">
              <img v-if="item.type == 'TODO'" src="@/assets/images/msg04.png" alt="" class="message-icon" />
              <img v-else-if="item.type == 'NOTIFY'" src="@/assets/images/msg01.png" alt="" class="message-icon" />
              <img v-else src="@/assets/images/msg02.png" alt="" class="message-icon" />
              <div class="message-content">
                <span class="message-title">{{ item.title }}</span>
                <span class="message-date">{{ useTime(item.create_at).nowTime.value }}</span>
              </div>
            </li>
          </ul>
          <div v-else class="message-empty">
            <img src="@/assets/images/notData.png" alt="notData" />
            <div>暂无通知</div>
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-popover>
    <el-dialog
      v-model="dialogVisible"
      :destroy-on-close="true"
      :overflow="true"
      :draggable="true"
      width="1000"
      top="50px"
      :title="messageTitle"
    >
      <div class="view" v-html="content"></div>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import apiService from "@/api/services/apiService";
import { Message } from "@/api/types/base";
import { useTime } from "@/hooks/useTime";
import { useUserStore } from "@/stores/modules/user";
import { useIntervalFn } from "@vueuse/core";
import { useInfiniteScroll } from "@vueuse/core";

const el = ref<HTMLElement | null>(null);

const userInfo = useUserStore().userInfo;
const activeName = ref("unread");
const unReadMessageList = ref<Message[]>([]);
const readMessageList = ref<Message[]>([]);
const dialogVisible = ref(false);
const content = ref("");
const messageTitle = ref("");
const readCount = ref(0);
let page = 0;
let pageSize = 5;

useInfiniteScroll(
  el,
  () => {
    findNextPageReadMessage();
  },
  { distance: 20 }
);

useIntervalFn(async () => {
  await findUnReadMessage();
}, 30000);

const unReadCount = computed(() => {
  return unReadMessageList.value.length;
});

const onShow = () => {
  findUnReadMessage();
};

const onReadMessage = async (item: Message) => {
  dialogVisible.value = true;
  content.value = item.summary;
  messageTitle.value = item.title;
  await readMessage(item);
  await findReadMessageCount();
  await findReadMessage();
};

const onOpenMessage = (item: Message) => {
  dialogVisible.value = true;
  content.value = item.summary;
  messageTitle.value = item.title;
};

const onHide = () => {
  activeName.value = "unread";
};

const readMessage = (message: Message) => {
  let readData = {
    messageId: message.messageId,
    user: userInfo._id,
    readDate: new Date()
  };
  apiService.save("messageState", readData).then(() => {
    unReadMessageList.value = unReadMessageList.value.filter(item => item._id !== message._id);
  });
};

const findUnReadMessage = () => {
  let groupCondition = [
    {
      $lookup: {
        from: "messagestates",
        localField: "messageId",
        foreignField: "messageId",
        as: "ms"
      }
    },
    {
      $match: {
        "ms.user": { $ne: userInfo._id },
        $or: [{ range: "all" }, { toUsers: { $in: [userInfo._id] } }]
      }
    },
    { $sort: { create_at: -1 } }
  ];
  apiService.groupNoLoading<Message[]>("message", groupCondition).then(({ data }) => {
    unReadMessageList.value = data;
  });
};

const findReadMessageCount = () => {
  let groupCondition = [
    {
      $lookup: {
        from: "messagestates",
        localField: "messageId",
        foreignField: "messageId",
        as: "ms"
      }
    },
    {
      $match: {
        "ms.user": userInfo._id,
        $or: [{ range: "all" }, { toUsers: { $in: [userInfo._id] } }]
      }
    },
    { $group: { _id: null, count: { $sum: 1 } } }
  ];
  apiService.group<any>("message", groupCondition).then(({ data }) => {
    if (data && data.length > 0) {
      readCount.value = data[0].count;
    }
  });
};

const findReadMessage = () => {
  readMessageList.value = [];
  page = 1;
  let groupCondition = [
    {
      $lookup: {
        from: "messagestates",
        localField: "messageId",
        foreignField: "messageId",
        as: "ms"
      }
    },
    {
      $match: {
        "ms.user": userInfo._id,
        $or: [{ range: "all" }, { toUsers: { $in: [userInfo._id] } }]
      }
    },
    { $sort: { create_at: -1 } },
    { $skip: (page - 1) * pageSize },
    { $limit: pageSize }
  ];
  apiService.group<Message[]>("message", groupCondition).then(({ data }) => {
    readMessageList.value = data;
  });
};

const findNextPageReadMessage = () => {
  if (page * pageSize > readCount.value) return;
  page = page + 1;
  let groupCondition = [
    {
      $lookup: {
        from: "messagestates",
        localField: "messageId",
        foreignField: "messageId",
        as: "ms"
      }
    },
    {
      $match: {
        "ms.user": userInfo._id,
        $or: [{ range: "all" }, { toUsers: { $in: [userInfo._id] } }]
      }
    },
    { $sort: { create_at: -1 } },
    { $skip: (page - 1) * pageSize },
    { $limit: pageSize }
  ];
  apiService.group<Message[]>("message", groupCondition).then(({ data }) => {
    readMessageList.value = readMessageList.value.concat(data);
  });
};

onMounted(() => {
  findUnReadMessage();
  findReadMessage();
  findReadMessageCount();
});
</script>

<style scoped lang="scss">
:deep(.el-dialog__body) {
  height: 480px !important;
  overflow: auto;
}
.message-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 260px;
  line-height: 45px;
}
.message-list {
  display: flex;
  flex-direction: column;
  height: 300px;
  padding: 0;
  margin: 0;
  overflow: auto;
  list-style: none;
  .message-item {
    display: flex;
    align-items: center;
    padding: 10px 0;
    cursor: pointer;
    border-bottom: 1px solid var(--el-border-color-light);
    &:last-child {
      border: none;
    }
    .message-icon {
      width: 40px;
      height: 40px;
      margin: 0 20px 0 5px;
    }
    .message-content {
      display: flex;
      flex-direction: column;
      .message-title {
        display: -webkit-box;
        width: 260px;
        margin-bottom: 5px;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
        overflow: hidden;
        text-overflow: ellipsis;
        &:hover {
          color: black;
        }
      }
      .message-date {
        font-size: 14px;
        color: var(--el-text-color-secondary);
      }
    }
  }
}
</style>
